#ifndef CHEF_H_
#define CHEF_H_

#include "dish.h"

typedef struct Chef_t *Chef;

typedef enum {
	CHEF_SUCCESS,
	CHEF_INVALID_ARGUMENT,
	CHEF_OUT_OF_MEMORY,
	CHEF_NO_DISHES
} ChefResult;

/**
 * Creates a new chef:
 * @param name, the new chef's name.
 * @param result, a pointer to a ChefResult, (ignore it in case of NULL).
 * result value:
 * CHEF_INVALID_ARGUMENT if one of the parameters is invalid.
 * CHEF_OUT_OF_MEMORY if a memory allocation failed.
 * CHEF_SUCCESS otherwise.
 * @return:
 * NULL in case of error.
 * a new Chef in case of success.
 */
Chef chefCreate(const char *name, ChefResult *result);

/**
 * Creates a copy of an existing chef:
 * @param chef, the Chef that we want to copy.
 * @param result, a pointer to a ChefResult, (ignore it in case of NULL).
 * *result value:
 * CHEF_INVALID_ARGUMENT if chef is NULL
 * CHEF_OUT_OF_MEMORY if a memory allocation failed.
 * CHEF_SUCCESS otherwise.
 * @return:
 * NULL in case of error.
 * a copy of an existing Chef in case of success.
 */
Chef chefCopy(Chef chef, ChefResult *result);

/**
 * Destroyes an existing chef:
 * @param chef the Chef that we want to destroy. (does nothing if it's NULL).
 */
void chefDestroy(Chef chef);

/**
 * Returns the name of the chef:
 * @param chef The Chef
 * @return
 * NULL if chef is NULL
 * The Chef's name, otherwise.
 * Note: the actual name is returned, so it will be invalid
 * after destroying chef.
 */
const char *chefGetName(Chef chef);

/**
 * Returns the Chef's score:
 * @param chef The Chef
 * @return
 * -1 if chef is NULL.
 * the chef's score, otherwise.
 */
int chefGetScore(Chef chef);

/**
 * Increments the Chef's score:
 * @param chef The Chef (does nothing if is NULL)
 */
void chefIncrementScore(Chef chef);

/**
 * adds a dish to the chef's priority queue of dishes:
 * @param chef the chef who cooked the dish.
 * @param dish the dish that we want to add.
 * @param favorite the priority of the new dish.
 * @param result a pointer to a ChefResult, (ignore it in case of NULL).
 * *result value:
 * CHEF_INVALID_ARGUMENT if one of the parameters is invalid.
 * CHEF_OUT_OF_MEMORY if a memory allocation failed.
 * CHEF_SUCCESS otherwise.
 */
void chefAddDish(Chef chef, Dish dish, int favorite,
		ChefResult *result);

/**
 * Returns the Chef's favorite Dish:
 * @param chef  contains the chef's priority queue of dishes.
 * @param result a pointer to a ChefResult, (ignore it in case of NULL).
 * *result value:
 * CHEF_INVALID_ARGUMENT if one of the parameters is invalid.
 * CHEF_NO_DISHES if the chef has no dishes yet.
 * CHEF_SUCCESS otherwise.
 * @return:
 * NULL in case of error.
 * the chef's favorite dish in case of success.
 * Note: the actual dish is being returned. not a copy of it.
 */
Dish chefGetFavoriteDish(Chef chef, ChefResult *result);

/**
 * Removes the Chef's favorite Dish:
 * @param chef contains the chef's priority queue of dishes.
 * @param result a pointer to a ChefResult, (ignore it in case of NULL).
 * *result value:
 * CHEF_INVALID_ARGUMENT if one of the parameters is invalid.
 * CHEF_NO_DISHES if the chef has no dishes yet.
 * CHEF_SUCCESS otherwise.
 */
void chefRemoveFavoriteDish(Chef chef, ChefResult *result);

#endif /* CHEF_H_ */
